﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Configuration;

namespace HgCo.WindowsLive.SkyDrive.TotalCommander.Plugins.Support
{
    /// <summary>
    /// Represents the configuration for SkyDriveWfx.
    /// </summary>
    public class SkyDriveWfxConfiguration
    {
        #region Properties

        /// <summary>
        /// Gets the assembly file.
        /// </summary>
        public static FileInfo AssemblyFile
        {
            get { return new FileInfo(Assembly.GetExecutingAssembly().Location); }
        }

        /// <summary>
        /// Gets the configuration file.
        /// </summary>
        public static FileInfo ConfigurationFile
        {
            get
            {
                var configFilePath = String.Format(
                    CultureInfo.InvariantCulture,
                    "{0}.config",
                    AssemblyFile.FullName);
                var fiConfig = new FileInfo(configFilePath);
                return fiConfig;
            }
        }

        /// <summary>
        /// Gets or sets the list of application settings.
        /// </summary>
        /// <value>The list of application settings.</value>
        private List<SkyDriveWfxApplicationSetting> ApplicationSettings { get; set; }

        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        /// <value>The name of the user.</value>
        public string UserName
        {
            get { return GetApplicationSettingValue("UserName"); }
            set { SetApplicationSettingValue("UserName", value); }
        }

        /// <summary>
        /// Gets or sets the password of the user.
        /// </summary>
        /// <value>The password.</value>
        public string UserPassword
        {
            get { return GetApplicationSettingValue("UserPassword"); }
            set { SetApplicationSettingValue("UserPassword", value); }
        }

        /// <summary>
        /// Gets or sets the Windows Live Identifier (CID).
        /// </summary>
        /// <value>The Cid.</value>
        public string Cid
        {
            get { return GetApplicationSettingValue("CID"); }
            set { SetApplicationSettingValue("CID", value); }
        }

        /// <summary>
        /// Gets or sets the connection type.
        /// </summary>
        /// <value>The connection type.</value>
        public SkyDriveWfxConnectionType ConnectionType
        {
            get
            {
                var connectionType = SkyDriveWfxConnectionType.Private;
                try
                {
                    connectionType = (SkyDriveWfxConnectionType)Enum.Parse(
                        typeof(SkyDriveWfxConnectionType),
                        GetApplicationSettingValue("ConnectionType"),
                        true);
                }
                catch { }
                return connectionType;
            }
            set { SetApplicationSettingValue("ConnectionType", value.ToString()); }
        }

        #endregion

        /// <summary>
        /// Prevents a default instance of the <see cref="SkyDriveWfxConfiguration"/> class from being created.
        /// </summary>
        private SkyDriveWfxConfiguration()
        {
            ApplicationSettings = new List<SkyDriveWfxApplicationSetting>();
        }

        #region Instance Methods

        /// <summary>
        /// Gets the application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <returns>The application setting.</returns>
        private SkyDriveWfxApplicationSetting GetApplicationSetting(string key)
        {
            return ApplicationSettings
                .FirstOrDefault(appSet => appSet.Key.Equals(key, StringComparison.CurrentCultureIgnoreCase));
        }

        /// <summary>
        /// Gets the value of an application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <returns>The value of the application setting.</returns>
        private string GetApplicationSettingValue(string key)
        {
            var appSet = GetApplicationSetting(key);
            return appSet != null ? appSet.Value : String.Empty;
        }

        /// <summary>
        /// Sets the value of an application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <param name="value">The value of the application setting.</param>
        private void SetApplicationSettingValue(string key, string value)
        {
            var appSet = GetApplicationSetting(key);
            if (appSet != null)
            {
                appSet.Value = value;
            }
            else
            {
                ApplicationSettings.Add(
                    new SkyDriveWfxApplicationSetting
                    {
                        Key = key,
                        Value = value
                    });
            }
        }

        /// <summary>
        /// Saves the configuration.
        /// </summary>
        public void Save()
        {
            Save(this);
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Loads the configuration.
        /// </summary>
        /// <returns>The configuration.</returns>
        public static SkyDriveWfxConfiguration Load()
        {
            var config = new SkyDriveWfxConfiguration();
            var cfg = ConfigurationManager.OpenExeConfiguration(AssemblyFile.FullName);
            foreach (KeyValueConfigurationElement appSetting in cfg.AppSettings.Settings)
            {
                config.ApplicationSettings.Add(
                    new SkyDriveWfxApplicationSetting
                        {
                            Key = appSetting.Key,
                            Value = appSetting.Value
                        });
            }
            return config;
        }

        /// <summary>
        /// Saves the configuration.
        /// </summary>
        /// <param name="config">The configuration to save.</param>
        public static void Save(SkyDriveWfxConfiguration config)
        {
            if (config != null)
            {
                var cfg = ConfigurationManager.OpenExeConfiguration(AssemblyFile.FullName);
                cfg.AppSettings.Settings.Clear();

                foreach (var appSetting in config.ApplicationSettings)
                {
                    cfg.AppSettings.Settings.Add(appSetting.Key, appSetting.Value);
                }

                cfg.Save(ConfigurationSaveMode.Full);
            }
        }

        #endregion
    }
}
